home *** CD-ROM | disk | FTP | other *** search
/ SGI Freeware 1999 August / SGI Freeware 1999 August.iso / dist / fw_hylafax.idb / usr / freeware / sbin / recvstats.z / recvstats
Encoding:
Text File  |  1999-07-16  |  9.0 KB  |  361 lines

  1. #! /bin/sh
  2. #    $Id: recvstats.sh.in,v 1.25 1996/06/24 03:06:25 sam Rel $
  3. #
  4. # HylaFAX Facsimile Software
  5. #
  6. # Copyright (c) 1990-1996 Sam Leffler
  7. # Copyright (c) 1991-1996 Silicon Graphics, Inc.
  8. # HylaFAX is a trademark of Silicon Graphics
  9. # Permission to use, copy, modify, distribute, and sell this software and 
  10. # its documentation for any purpose is hereby granted without fee, provided
  11. # that (i) the above copyright notices and this permission notice appear in
  12. # all copies of the software and related documentation, and (ii) the names of
  13. # Sam Leffler and Silicon Graphics may not be used in any advertising or
  14. # publicity relating to the software without the specific, prior written
  15. # permission of Sam Leffler and Silicon Graphics.
  16. # THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
  17. # EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
  18. # WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
  19. # IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
  20. # ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
  21. # OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  22. # WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
  23. # LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
  24. # OF THIS SOFTWARE.
  25. #
  26.  
  27. #
  28. # Print Statistics about Received Facsimile.
  29. #
  30. SPOOL=/usr/freeware/var/spool/fax
  31.  
  32. test -f $SPOOL/etc/setup.cache || {
  33.     cat<<EOF
  34.  
  35. FATAL ERROR: $SPOOL/etc/setup.cache is missing!
  36.  
  37. The file $SPOOL/etc/setup.cache is not present.  This
  38. probably means the machine has not been setup using the faxsetup(1M)
  39. command.  Read the documentation on setting up HylaFAX before you
  40. startup a server system.
  41.  
  42. EOF
  43.     exit 1
  44. }
  45. . $SPOOL/etc/setup.cache
  46.  
  47. FILES=
  48. SORTKEY=-sender                # default is to sort by sender
  49. TODAY="`date +'%D %H:%M'`"
  50. AGE="360"                # report statistics for last year
  51. SINCE=
  52.  
  53. while [ x"$1" != x"" ] ; do
  54.     case $1 in
  55.     -send*|-csi|-dest*|-speed|-rate|-format)
  56.         SORTKEY=$1;;
  57.     -age)   shift; AGE=$1;;
  58.     -since) shift; SINCE=$1;;
  59.     -*)        echo "Usage: $0 [-sortkey] [-age days] [-since date] [files]"
  60.         exit 1
  61.         ;;
  62.     *)        FILES="$FILES $1";;
  63.     esac
  64.     shift
  65. done
  66. if [ -z "$FILES" ]; then
  67.     FILES=$SPOOL/etc/xferlog
  68. fi
  69.  
  70. #
  71. # Construct awk rules to collect information according
  72. # to the desired sort key.  There are multiple rules for
  73. # dealing with the different formats that have existed
  74. # over time.
  75. #
  76. case $SORTKEY in
  77. -send*|-csi)
  78.     AWKRULES='
  79.     $2 == "RECV" && NF == 9  { acct($3, $7, $8, $5, $6, $9); }
  80.     $2 == "RECV" && NF == 11 { acct($6, $9, $10, $7, $8, $11); }
  81.     $2 == "RECV" && NF == 12 { acct($7, $10, $11, $8, $9, $12); }
  82.     $2 == "RECV" && NF == 13 { acct($9, $11, $12, getBR($10), getDF($10), $13); }
  83.     $2 == "RECV" && NF == 14 { acct($9, $11, $13, getBR($10), getDF($10), $14); }
  84.     '
  85.     ;;
  86. -dest*)
  87.     AWKRULES='
  88.     $2 == "RECV" && NF == 9  { acct($4, $7, $8, $5, $6, $9); }
  89.     $2 == "RECV" && NF == 11 { acct($5, $9, $10, $7, $8, $11); }
  90.     $2 == "RECV" && NF == 12 { acct($6, $10, $11, $8, $9, $12); }
  91.     $2 == "RECV" && NF == 14 { acct($8, $11, $13, getBR($10), getDF($10), $14); }
  92.     '
  93.     ;;
  94. -speed|-rate)
  95.     AWKRULES='
  96.     $2 == "RECV" && NF == 9  { acct($5, $7, $8, $5, $6, $9); }
  97.     $2 == "RECV" && NF == 11 { acct($7, $9, $10, $7, $8, $11); }
  98.     $2 == "RECV" && NF == 12 { acct($8, $10, $11, $8, $9, $12); }
  99.     $2 == "RECV" && NF == 13 { acct(getBR($10), $11, $12, getBR($10), getDF($10), $13); }
  100.     $2 == "RECV" && NF == 14 { acct(getBR($10), $11, $13, getBR($10), getDF($10), $14); }
  101.     '
  102.     ;;
  103. -format)
  104.     AWKRULES='
  105.     $2 == "RECV" && NF == 9  { acct($6, $7, $8, $5, $6, $9); }
  106.     $2 == "RECV" && NF == 11 { acct($8, $9, $10, $7, $8, $11); }
  107.     $2 == "RECV" && NF == 12 { acct($9, $10, $11, $8, $9, $12); }
  108.     $2 == "RECV" && NF == 13 { acct(getDF($10), $11, $12, getBR($10), getDF($10), $13); }
  109.     $2 == "RECV" && NF == 14 { acct(getDF($10), $11, $13, getBR($10), getDF($10), $14); }
  110.     '
  111.     ;;
  112. esac
  113.  
  114. #
  115. # Generate an awk program to process the statistics file.
  116. #
  117. tmpAwk=/tmp/xfer$$
  118. trap "rm -f $tmpAwk; exit 1" 0 1 2 15
  119.  
  120. ($CAT<<'EOF'
  121. #
  122. # Setup date conversion data structures.
  123. #
  124. function setupDateTimeStuff()
  125. {
  126.     daysInMonth[ 0] = 31; daysInMonth[ 1] = 28; daysInMonth[ 2] = 31;
  127.     daysInMonth[ 3] = 30; daysInMonth[ 4] = 31; daysInMonth[ 5] = 30;
  128.     daysInMonth[ 6] = 31; daysInMonth[ 7] = 31; daysInMonth[ 8] = 30;
  129.     daysInMonth[ 9] = 31; daysInMonth[10] = 30; daysInMonth[11] = 31;
  130.  
  131.     FULLDAY = 24 * 60 * 60;
  132. }
  133.  
  134. #
  135. # Convert hh:mm:ss to seconds.
  136. #
  137. function cvtTime(s)
  138. {
  139.     t = i = 0;
  140.     for (n = split(s, a, ":"); i++ < n; )
  141.     t = t*60 + a[i];
  142.     return t;
  143. }
  144.  
  145. #
  146. # Convert MM/DD/YY hh:mm to seconds.
  147. # NB: this does not deal with leap years.
  148. #
  149. function cvtDateTime(s)
  150. {
  151.     yday = substr(s,7,2)*365 + substr(s,4,2) - 1;
  152.     mon = substr(s,0,2) + 0;
  153.     for (i = 0; i < mon; i++)
  154.     yday += daysInMonth[i];
  155.     return yday*FULLDAY + cvtTime(substr(s,10) ":00");
  156. }
  157.  
  158. function setupDigits()
  159. {
  160.   digits[0] = "0"; digits[1] = "1"; digits[2] = "2";
  161.   digits[3] = "3"; digits[4] = "4"; digits[5] = "5";
  162.   digits[6] = "6"; digits[7] = "7"; digits[8] = "8";
  163.   digits[9] = "9";
  164. }
  165.  
  166. #
  167. # Format seconds as hh:mm:ss.
  168. #
  169. function fmtTime(t)
  170. {
  171.     v = int(t/3600);
  172.     result = "";
  173.     if (v > 0) {
  174.     if (v >= 10)
  175.         result = digits[int(v/10)];
  176.     result = result digits[int(v%10)] ":";
  177.     t -= v*3600;
  178.     }
  179.     v = int(t/60);
  180.     if (v >= 10 || result != "")
  181.     result = result digits[int(v/10)];
  182.     result = result digits[int(v%10)];
  183.     t -= v*60;
  184.     return (result ":" digits[int(t/10)] digits[int(t%10)]);
  185. }
  186.  
  187. #
  188. # Setup map for histogram calculations
  189. # and indexed table for decoding params.
  190. #
  191. function setupMaps(s, map, names)
  192. {
  193.     n = split(s, a, ":");
  194.     for (i = 1; i <= n; i++) {
  195.     map[a[i]] = i;
  196.     names[i-1] = a[i];
  197.     }
  198. }
  199.  
  200. #
  201. # Add pages to a histogram.
  202. #
  203. function addToMap(key, ix, pages, map)
  204. {
  205.     if (key == "") {
  206.     for (i in map)
  207.         key = key ":";
  208.     }
  209.     n = split(key, a, ":");
  210.     a[map[ix]] += pages;
  211.     t = a[1];
  212.     for (i = 2; i <= n; i++)
  213.       t = t ":" a[i];
  214.     return t;
  215. }
  216.  
  217. #
  218. # Return the name of the item with the
  219. # largest number of accumulated pages.
  220. #
  221. function bestInMap(totals, map)
  222. {
  223.    n = split(totals, a, ":");
  224.    imax = 1; max = -1;
  225.    for (j = 1; j <= n; j++)
  226.        if (a[j] > max) {
  227.        max = a[j];
  228.        imax = j;
  229.        }
  230.    split(map, a, ":");
  231.    return a[imax];
  232. }
  233.  
  234. #
  235. # Sort array a[l..r]
  236. #
  237. function qsort(a, l, r) {
  238.     i = l;
  239.     k = r+1;
  240.     item = a[l];
  241.     for (;;) {
  242.     while (i < r) {
  243.             i++;
  244.         if (a[i] >= item)
  245.         break;
  246.         }
  247.     while (k > l) {
  248.             k--;
  249.         if (a[k] <= item)
  250.         break;
  251.         }
  252.         if (i >= k)
  253.         break;
  254.     t = a[i]; a[i] = a[k]; a[k] = t;
  255.     }
  256.     t = a[l]; a[l] = a[k]; a[k] = t;
  257.     if (k != 0 && l < k-1)
  258.     qsort(a, l, k-1);
  259.     if (k+1 < r)
  260.     qsort(a, k+1, r);
  261. }
  262.  
  263. function getBR(params)
  264. {
  265.     return brNames[int(int(params) / 2) % 8];
  266. }
  267.  
  268. function getDF(params)
  269. {
  270.     return dfNames[int(int(params) / 512) % 4];
  271. }
  272.  
  273. #
  274. # Accumulate a statistics record.
  275. #
  276. function acct(key, pages, time, br, df, status)
  277. {
  278.     if (cvtDateTime($1) < KEEP)
  279.     return;
  280.     gsub("\"", "", key);
  281.     gsub("^ +", "", key);
  282.     gsub(" +$", "", key);
  283.     recvpages[key] += pages;
  284.     if (pages == 0 && time > 60)
  285.     time = 0;
  286.     recvtime[key] += cvtTime(time);
  287.     gsub("\"", "", status);
  288.     if (status != "")
  289.     recverrs[key]++;
  290.     gsub("\"", "", br);
  291.     recvrate[key] = addToMap(recvrate[key], br, pages, rateMap);
  292.     gsub("\"", "", df);
  293.     recvdata[key] = addToMap(recvdata[key], df, pages, dataMap);
  294. }
  295.  
  296. #
  297. # Print a rule between the stats and the totals line.
  298. #
  299. function printRule(n, s)
  300. {
  301.     r = "";
  302.     while (n-- >= 0)
  303.     r = r s;
  304.     printf "%s\n", r;
  305. }
  306.  
  307. BEGIN        { FS="\t";
  308.           rates = "2400:4800:7200:9600:12000:14400";
  309.           setupMaps(rates, rateMap, brNames);
  310.           datas = "1-D MR:2-D MR:2-D Uncompressed Mode:2-D MMR";
  311.           setupMaps(datas, dataMap, dfNames);
  312.           setupDateTimeStuff();
  313.           if (SINCE == "")
  314.               KEEP = cvtDateTime(TODAY) - AGE*FULLDAY;
  315.           else
  316.               KEEP = cvtDateTime(SINCE);
  317.         }
  318. END        { OFS="\t"; setupDigits();
  319.           maxlen = 15;
  320.           nsorted = 0;
  321.           for (i in recvpages) {
  322.               l = length(i);
  323.               if (l > maxlen)
  324.             maxlen = l;
  325.               sorted[nsorted++] = i;
  326.           }
  327.           qsort(sorted, 0, nsorted-1);
  328.           fmt = "%-" maxlen "." maxlen "s";    # e.g. %-24.24s
  329.           printf fmt " %5s %8s %6s %4s %7s %7s\n",
  330.               "Sender", "Pages", "Time", "Pg/min",
  331.               "Errs", "TypRate", "TypData";
  332.           tpages = 0;
  333.           ttime = 0;
  334.           terrs = 0;
  335.           for (k = 0; k < nsorted; k++) {
  336.               i = sorted[k];
  337.               t = recvtime[i]/60; if (t == 0) t = 1;
  338.               n = recvpages[i]; if (n == 0) n = 1;
  339.               brate = best
  340.               printf fmt " %5d %8s %6.1f %4d %7d %7s\n",
  341.               i, recvpages[i], fmtTime(recvtime[i]),
  342.               recvpages[i] / t, recverrs[i],
  343.               bestInMap(recvrate[i], rates),
  344.               bestInMap(recvdata[i], datas);
  345.             tpages += recvpages[i];
  346.             ttime += recvtime[i];
  347.             terrs += recverrs[i];
  348.           }
  349.           printRule(maxlen+1+5+1+8+6+1+4+1+7+1+7, "-");
  350.           t = ttime/60; if (t == 0) t = 1;
  351.           printf fmt " %5d %8s %6.1f %4d\n",
  352.               "Total", tpages, fmtTime(ttime), tpages/t, terrs;
  353.         }
  354. EOF
  355. echo "$AWKRULES"
  356. )>$tmpAwk
  357. $AWK -f $tmpAwk -v TODAY="$TODAY" -v AGE="$AGE" -v SINCE="$SINCE" $FILES
  358.